package com.jyn.marqueetextview;

import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Typeface;
import android.text.Html;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.URLSpan;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.util.Xml;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import org.xmlpull.v1.XmlPullParser;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 左右滚动跑马灯
 */
public class MarqueeView extends HorizontalScrollView {

    private TextView mTextView;
    private TextView mGhostTextView;

    private int viewWidth;

    private CharSequence mText;
    private int measureText;
    private int textColor = 0xff000000;

    private int mOffset = 0;
    private int mGhostOffset = 0;

    /**
     * 间隔
     */
    private int spacing = 1000;

    /**
     * 移动速度
     */
    private int speed = 1;
    /**
     *          Right_2_Left   ,// 从右到左 0
     *         Left_2_Right   ,// 从左到右 1
     *         Down_2_Up      ,// 从下到上 2
     */
    private int scrollerType;

    //粗斜体
    public static final String CUTI = "1";
    public static final String XIETI = "2";
    public static final String CUXIETI = "3";

    private ValueAnimator valueAnimator;
    private int textSize = 14;
    private Context mContext;

    public MarqueeView(Context context) {
        this(context, null);
    }

    public MarqueeView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MarqueeView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initAttrs(context, attrs);
        initLayout();
        initAnim();
    }

    @SuppressLint("Recycle")
    private void initAttrs(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MarqueeView);
        textColor = typedArray.getColor(R.styleable.MarqueeView_textColor, textColor);
        if (typedArray.hasValue(R.styleable.MarqueeView_textSize)) {
            textSize = (int) typedArray.getDimension(R.styleable.MarqueeView_textSize, textSize);
            textSize = px2sp(context, textSize);
        }

        if (typedArray.hasValue(R.styleable.MarqueeView_spacing)) {
            spacing = (int) typedArray.getDimension(R.styleable.MarqueeView_spacing, spacing);
        }

        if (typedArray.hasValue(R.styleable.MarqueeView_speed)) {
            speed = (int) typedArray.getInteger(R.styleable.MarqueeView_speed, 2);
        }
        mContext = context;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        viewWidth = getMeasuredWidth();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (measureText > viewWidth) {
            startAnim();
        } else {
            stopAnim();
        }
    }

    private void initLayout() {
        RelativeLayout relativeLayout = new RelativeLayout(getContext());
        LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        relativeLayout.setLayoutParams(layoutParams);
        addView(relativeLayout);

        mTextView = createTextView();
        mGhostTextView = createTextView();

        relativeLayout.addView(mTextView);
        relativeLayout.addView(mGhostTextView);
    }

    private void initAnim() {
        valueAnimator = ValueAnimator.ofFloat(0, measureText);
        valueAnimator.addUpdateListener(animatorUpdateListener);
        valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
        valueAnimator.setRepeatMode(ValueAnimator.RESTART);
    }

    public void setSpacing(int spacing) {
        this.spacing = spacing;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    public void setText(CharSequence text) {
        this.mText = text;
//        buildMsgText(mTextView);
//        buildMsgText(mGhostTextView);
        mTextView.setText(mText);
        mGhostTextView.setText(mText);


        measureText = (int) mTextView.getPaint().measureText(mText, 0, mText.length());
        resetMarqueeView();
        int sceenWidth = getScreenWidth((Activity) mContext);
        if (measureText < sceenWidth){
            int x =  sceenWidth-measureText;
            int spceWidth = (int) mTextView.getPaint().measureText(" ", 0, " ".length());
            int count = x/spceWidth;
            for (int i = 0;i<count;i++){
                text = text+" ";
            }
            this.mText = text;
            mTextView.setText(mText);
            mGhostTextView.setText(mText);
            spacing = x;
            measureText = (int) mTextView.getPaint().measureText(mText, 0, mText.length());
        }
        if (measureText > viewWidth) {
            startAnim();
        } else {
            stopAnim();
        }
    }

    private TextView createTextView() {
        TextView textView = new TextView(getContext());
        textView.setPadding(0, 0, 0, 0);
        textView.setSingleLine();
        textView.setTextColor(textColor);
        textView.setTextSize(textSize);

        LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
        textView.setLayoutParams(layoutParams);
        textView.setGravity(Gravity.CENTER_VERTICAL);
        textView.setMovementMethod(LinkMovementMethod.getInstance());
        return textView;
    }

    private int getScreenWidth(Activity context) {
        //方法三：应用程序显示区域指定可能包含应用程序窗口的显示部分，不包括系统装饰
        DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
        int width = displayMetrics.widthPixels;
        return width;
    }

    private void resetMarqueeView() {
        mOffset = 0;
        mGhostOffset = measureText + spacing;
        mGhostTextView.setX(mGhostOffset);
        invalidate();
    }

    public void startAnim() {
        valueAnimator.setDuration((long) measureText);
        stopAnim();
        valueAnimator.start();
    }

    public void stopAnim() {
        valueAnimator.cancel();
        resetMarqueeView();
    }


    ValueAnimator.AnimatorUpdateListener animatorUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            mOffset -= speed;
            mGhostOffset -= speed;
            if (mOffset + measureText < 0) {
                mOffset = mGhostOffset + measureText + spacing;
            }
            if (mGhostOffset + measureText < 0) {
                mGhostOffset = mOffset + measureText + spacing;
            }
            invalidate();
        }
    };


    // 将px值转换为sp值
    public static int px2sp(Context context, float pxValue) {
        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
        return (int) (pxValue / fontScale + 0.5f);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mTextView == null || mGhostTextView == null) {
            return;
        }
        switch (scrollerType){
            case 0:
                mTextView.setX(mOffset);
                mGhostTextView.setX(mGhostOffset);
                break;
            case 1:
                mTextView.setX(-mOffset);
                mGhostTextView.setX(-mGhostOffset);
                break;
        }

    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return true;
    }

    private String xmlMsgToStr(String xmlMsg) {
        String PATTEN_STR1 = "<span id=\"title\">.+?</span>|<span id=\"name\">.+?</span>|<p>|</p>|<TextFlow .+?>|</TextFlow>";
        String titelStr = "";
        String nameStr = "";
        InputStream inStream = new ByteArrayInputStream(xmlMsg.getBytes());
        XmlPullParser pullParser = Xml.newPullParser();
        try {
            pullParser.setInput(inStream, "UTF-8");
            int event = pullParser.getEventType();
            while (event != XmlPullParser.END_DOCUMENT) {
                switch (event) {
                    case XmlPullParser.START_DOCUMENT:

                        break;
                    case XmlPullParser.START_TAG:
                        if ("span".equals(pullParser.getName())) {
                            if (pullParser.getAttributeValue(0).equals("title")) {
                                titelStr = pullParser.nextText() + " ";
                            } else if (pullParser.getAttributeValue(0).equals("name")) {
                                nameStr = pullParser.nextText();
                            }
                        }
                        break;
                    case XmlPullParser.END_TAG:
                        break;
                    default:
                }
                event = pullParser.next();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        Pattern pattern = Pattern.compile(PATTEN_STR1);
        Matcher matcher = pattern.matcher(xmlMsg);
        while (matcher.find()) {
            xmlMsg = xmlMsg.replace(matcher.group(), "");
        }
        return titelStr + nameStr + xmlMsg;
    }

    private Spanned fromHtml(String source) {
        return Html.fromHtml(xmlMsgToStr(source));
    }

    private void buildMsgText(TextView textView) {
        textView.setText(mText);
        CharSequence str = textView.getText();

        if (str instanceof Spannable) {
            int end = str.length();
            Spannable sp = (Spannable) str;
            URLSpan[] urls = sp.getSpans(0, end, URLSpan.class);
            SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(str);
            spannableStringBuilder.clearSpans();
            spannableStringBuilder.setSpan(new ForegroundColorSpan(Color.parseColor("#000000")), 0, mText.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
//            spannableStringBuilder.setSpan(new ForegroundColorSpan(Color.parseColor("#FFFB00")), mText.length(), titelStr.length() + nameStr.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
            for (URLSpan url : urls) {
                String jumpUrl = url.getURL();
                MarqueeLayoutUrlClickSpan myURLSpan = new MarqueeLayoutUrlClickSpan(jumpUrl);
                spannableStringBuilder.setSpan(myURLSpan, sp.getSpanStart(url), sp.getSpanEnd(url), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
            textView.setText(spannableStringBuilder);
        }
    }

    private class MarqueeLayoutUrlClickSpan extends ClickableSpan {
        private String url;

        public MarqueeLayoutUrlClickSpan(String url) {
            this.url = url;
        }

        @Override
        public void updateDrawState(TextPaint ds) {
            //设置超链接字体颜色
            ds.linkColor = Color.parseColor("#FFFFFF");
            super.updateDrawState(ds);
            ds.setUnderlineText(true);
        }

        @Override
        public void onClick(View widget) {

        }
    }

    public void setScrollerType(int scrollerType) {
        this.scrollerType = scrollerType;
    }

    public void setFontStyle(String ttfName){
        Typeface mtypeface= Typeface.createFromAsset(getContext().getAssets(),ttfName);
        mTextView.setTypeface(mtypeface);
        mGhostTextView.setTypeface(mtypeface);
    }

    public void setFontBold(String bold){
        switch (bold){
            case CUTI:
                mTextView.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD);
                mGhostTextView.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD);
                break;
            case XIETI:
                mTextView.setTypeface(Typeface.SANS_SERIF, Typeface.ITALIC);
                mGhostTextView.setTypeface(Typeface.SANS_SERIF, Typeface.ITALIC);
                break;
            case CUXIETI:
                mTextView.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD_ITALIC);
                mGhostTextView.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD_ITALIC);
                break;
        }
    }
}
